#!/usr/bin/env bash
# Copyright (c) 2021 maminjie <canpool@163.com>
# SPDX-License-Identifier: MulanPSL-2.0

method_def oec packageinit

usage_oec() {
    module_usage "oec" "openEuler/src-openEuler command-line tool"
}

do_oec() {
    module_do "oec" "$@"
}

oec_usage_help() {
    module_usage_help oec
}

# oec_do_help subcmd
oec_do_help() {
    module_do_help oec "$1"
}

# __oec_get_subcmd cmd
#   Get the fullname of cmd
# Returns:
#   "" or fullname
__oec_get_subcmd() {
    local cmd=""
    case "${1}" in
        "h"|"help")
            cmd="help"
            ;;
        "finddeveloper"|"fdev")
            cmd="finddeveloper"
            ;;
        "pi"|"patchinfo"|"patinfo")
            cmd="patchinfo"
            ;;
        "rl"|"release")
            cmd="release"
            ;;
        *)
            ;;
    esac
    echo "$cmd"
}

usage_packageinit() {
printf "packageinit (pkginit): Init package to gitee, including fork, clone, push, pr.

Usage:
    ${PROG} pkginit SOURCEDIR TARGETDIR OWNER PKGLIST [BRANCH] [PRDESC] [SUMMARY]

Params:
    SOURCEDIR - The source directory that contains specific packages
    TARGETDIR - The target directory, where the packages are generally cloned from gitrepo
    OWNER - The upstream owner of package, as: src-openeuler
    PKGLIST - package string list, as: \"pkg1 pkg2 pkg3\" or pkg1 (single package)
              package list file that contains pkgnames (one per line or space separated)
    BRANCH - (optional) target branch, default is current branch of gitrepository
    PRDESC - (optional) the pr description, default is \"\"
    SUMMARY - (optional) the commit summary and pr title, default is \"Package init\"

Examples:
    ${PROG} pkginit /home/mine/src /home/mine/dst src-openeuler \"a b\"
                    Submit the two packages a and b to src-openeuler (fork, clone, push, pr).
                    sourcefiles in /home/mine/src and repos are cloned in /home/mine/dst

    ${PROG} pkginit /home/mine/src /home/mine/dst src-openeuler repo.txt
                    the repo.txt file contains pkgnames, you can use \"ls /home/mine/src > repo.txt\" to generate it.

    ${PROG} pkginit /home/mine/src /home/mine/dst src-openeuler \"a b\" openEuler-22.03-LTS-Next

    ${PROG} pkginit /home/mine/src /home/mine/dst src-openeuler \"c d\" openEuler-22.03-LTS-Next \"https://xxx/issue/yyy\" \"init package\"
                    PRDESC is issue address
\n"
}

# __oec_submitpkg src_dir dst_dir owner repo comments prurl [branch] [prdesc]
# Params
#   prurl - [O] the pr url
#   branch - [I] (optional) target branch
__oec_submitpkg() {
    local src_dir=$1
    local dst_dir=$2
    local owner=$3
    local repo=$4
    local comments="$5"
    local branch="$7"
    local pr_desc="$8"
    local srcpath=$src_dir/$repo
    local dstpath=$dst_dir/$repo

    # clone
    if [ ! -d $dstpath ]; then
        pushd "$dst_dir" || exit 1
        git clone https://gitee.com/$__oec_id/$repo.git
        popd || exit 1
    fi

    if [ ! -d $srcpath ] || [ ! -d $dstpath ]; then
        exit 2
    fi

    cp "$srcpath"/* "$dstpath"
    pushd "$dstpath" || exit
    gec_pushcode "$comments"
    local __prurl__=""
    gec_createpr "$owner" "$repo" "$comments" __prurl__ "$branch" "$pr_desc"
    eval $6=\"$__prurl__\"
    popd || exit
}

alias_def packageinit pkginit
# do_packageinit src_dir dst_dir owner repo_list [branch] [prdesc] [summary]
do_packageinit() {
    if [ $# -lt 4 ]; then
        usage_packageinit; exit
    fi
    local src_dir=$1
    local dst_dir=$2
    local owner=$3
    local repo_list=$(get_list "$4")
    local branch="$5"
    local pr_desc="$6"
    local summary="$7"
    local prurls=()

    if [ -n "$repo_list" ]; then
        gec_init
    fi

    for pkg in $repo_list; do
        gec_check_repo "$pkg"
        if [ $? -eq 0 ]; then
            echo -n "forking $pkg: "
            gitee_fork_repo "$owner" "$pkg"
            if [ $? -ne 0 ]; then
                color_print "$CLR_RED" "failed"
                continue
            else
                color_print "$CLR_GREEN" "success"
            fi
        fi
        sleep 2
        local prurl=""
        if [ -z "$summary" ]; then
            summary="Package init"
        fi
        __oec_submitpkg "$src_dir" "$dst_dir" "$owner" "$pkg" "$summary" prurl "$branch" "$pr_desc"
        if [ -n "$prurl" ]; then
            array_add prurls "$prurl"
        fi
        sleep 1
    done
    if [ ${#prurls[@]} -gt 0 ]; then
        echo "----PRs----"
        array_uniq prurls
    fi
}

oec_usage_finddeveloper() {
printf "finddeveloper (fdev): Find the developer of package

usage:
    ${PROG} oec fdev SPEC
    ${PROG} oec fdev repo [owner] [branch]

params:
    SPEC - spec file
    owner - the owner of repo, default is src-openeuler (optional)
    branch - the branch of repo, default is master (optional)
\n"
}

# oec_do_finddeveloper spec
# oec_do_finddeveloper repo [owner] [branch]
oec_do_finddeveloper() {
    if [ $# -lt 1 ]; then
        oec_usage_finddeveloper; exit
    fi
    if [ -f "$1" ]; then
        spec_get_developer "$1"
    else
        local repo="$1"
        local owner="$2"
        local branch="$3"
        if [ -z "$owner" ]; then
            owner="src-openeuler"
        fi
        if [ -z "$branch" ]; then
            branch="master"
        fi
        gec_init
        local specdata="$(gec_get_contents "$owner" "$repo" "$repo.spec" "$branch")"
        if [ -z "$specdata" ]; then
            return
        fi
        spec_get_developer "$specdata"
    fi
}

oec_usage_patchinfo() {
printf "patchinfo (patinfo, pi): Parse openEuler package patch infos

usage:
    ${PROG} oec patinfo DIR

params:
    DIR - the directory of repo[s]
\n"
}

# oec_do_patchinfo DIR
oec_do_patchinfo() {
    if [[ $# -lt 1 || ! -d "$1" ]]; then
        oec_usage_patchinfo; exit
    fi
    local dir=$(realpath "$1")
    local specs=$(find "$dir" -name *.spec)
    echo "package,patch_number,patch,desc,stat,insertion(+),deletion(-)"
    OLD_IFS=$IFS
    IFS=$'\n'
    for spec in $specs; do
        # package name
        local spec_dir=$(dirname "$spec")
        local spec_name=$(basename "$spec")
        spec_name=${spec_name%.spec}
        local patches=$(grep -E "^Patch[0-9]+" "$spec")
        for patch in $patches; do
            local patch_number=$(echo "$patch" | cut -d : -f 1 | sed 's/\s\+//g')
            local patch_name=$(echo "$patch" | cut -d : -f 2 | sed 's/\s\+//g')
            patch_name=$(echo "$patch_name" | sed "s/%{name}/$spec_name/g")
            local patch_path=$spec_dir/$patch_name
            local desc=$(sed -e '/^diff/,$d' -e '/^---/,$d' $patch_path | head -n100 | sed 's/"/""/g')
            local stat=$(patch_stat "$patch_path")
            local changes=$(echo "$stat" | grep -E "file[s]? changed") # (file|files)
            stat=$(echo "$stat" | sed 's/"/""/g' | head -n50)
            local insertion=$(echo "$changes" | awk '{print $4}')
            [[ -z "$insertion" ]] && insertion=0
            local deletion=$(echo "$changes" | awk '{print $6}')
            [[ -z "$deletion" ]] && deletion=0
            echo "$spec_name,$patch_number,$patch_name,\"$desc\",\"$stat\",$insertion,$deletion"
        done
    done
    IFS=$OLD_IFS
}

oec_usage_release() {
printf "release (rl): A tool for obtaining information about openeuler releases

usage:
    ${PROG} oec rl [options] [args]

$(bash ${BASH_SOURCE[0]%/*}/script/release.bash -h | sed '1,5d')
\n"
}

oec_do_release() {
    if [ $# -lt 1 ]; then
        oec_usage_release; exit
    fi
    bash "${BASH_SOURCE[0]%/*}/script/release.bash" "$@"
}
